package com.liming.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liming.auth.mapper.UserActivityMapper;
import com.liming.auth.service.UserActivityService;
import com.liming.common.constant.SystemConstants;
import com.liming.common.enums.DateScopeEnum;
import com.liming.common.enums.OperationTypeEnum;
import com.liming.common.exception.BusinessException;
import com.liming.common.pojo.dto.authinfo.UserActivityAddDTO;
import com.liming.common.pojo.entity.authinfo.UserActivity;
import com.liming.common.util.BeanUtils;
import com.liming.common.util.ThreadLocalUtils;
import com.liming.common.util.TimeUtils;
import com.liming.common.util.mybatisplus.MPUtil;
import com.liming.order.client.UserOrderClient;
import com.liming.product.client.ProductClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author liming
 * @date 2025/3/11
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserActivityServiceImpl extends ServiceImpl<UserActivityMapper, UserActivity>
        implements UserActivityService, MPUtil<UserActivity> {

    private final ProductClient productClient;
    private final UserOrderClient userOrderClient;


    @Override
    public Boolean saveActivityLog(UserActivityAddDTO dto) {
        UserActivity save = BeanUtils.toBean(dto, UserActivity.class);
        Assert.isTrue(save(save), () -> new BusinessException("用户行为日志保存失败"));
        return true;
    }

    @Override
    public Map<Long, Double> userActivityScoreMap(List<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return Map.of();
        }
        // 根据用户ID分组，再根据操作类型分组
        Map<Long, Map<Integer, List<UserActivity>>> collect = lambdaQuery().in(UserActivity::getUserId, userIds).list()
                .stream()
                .collect(Collectors.groupingBy(UserActivity::getUserId, Collectors.groupingBy(UserActivity::getOperationType, Collectors.toList())));
        Map<Long, Double> userIdAndScore = new HashMap<>();
        for (Map.Entry<Long, Map<Integer, List<UserActivity>>> entry : collect.entrySet()) {
            Long userId = entry.getKey();
            Map<Integer, List<UserActivity>> activityClassify = entry.getValue();
            double score = 0.0;
            for (Map.Entry<Integer, List<UserActivity>> activityEntry : activityClassify.entrySet()) {
                Integer operationType = activityEntry.getKey();
                List<UserActivity> userActivityList = activityEntry.getValue();
                Double rate = OperationTypeEnum.getRateByCode(operationType);
                // 如果是下单的行为，特殊处理
                if (ObjectUtil.equal(operationType, OperationTypeEnum.ORDER_PAY.getCode())) {
                    // 遍历该用户所有金额
                    for (UserActivity userActivity : userActivityList) {
                        score += rate * userActivity.getOrderAmount().doubleValue();
                    }
                    continue;
                }
                score += rate * userActivityList.size();
            }
            userIdAndScore.put(userId, score);
        }
        return userIdAndScore;
    }

    @Override
    public Integer activityUserCount(String scope) {
        TimeUtils.LocalDateTimeRange range = TimeUtils.getByDateScopeEnum(DateScopeEnum.getByScope(scope));
        // 这查出来的只是所有用户 的 所有的登录次数， 去重
        Map<Long, List<UserActivity>> collect = lambdaQuery()
                .eq(UserActivity::getOperationType, OperationTypeEnum.LOGIN.getCode())
                .ge(UserActivity::getCreateTime, range.getStart())
                .le(UserActivity::getCreateTime, range.getEnd())
                .list().stream().collect(Collectors.groupingBy(UserActivity::getUserId));
        return collect.size();
    }

    @Override
    public Map<Long, List<Integer>> productIdActivityTypeListMap() {
        return lambdaQuery()
                .in(UserActivity::getOperationType, OperationTypeEnum.productActivityTypeList())
                .isNotNull(UserActivity::getKeyId)
                .list()
                .stream()
                .collect(Collectors.groupingBy(UserActivity::getKeyId, Collectors.mapping(UserActivity::getOperationType, Collectors.toList())));
    }

    @Override
    public Map<Integer, List<Long>> activityBrandAndCategoryListMap(Long userId, Integer code) {
        if (ObjectUtil.isNotNull(userId)) {
            ThreadLocalUtils.set(SystemConstants.ID, userId.toString());
        }
        // 只查出最近的5条行为
        List<UserActivity> activityList = lambdaQuery()
                .eq(UserActivity::getUserId, ThreadLocalUtils.get(SystemConstants.ID))
                .eq(UserActivity::getOperationType, code)
                .orderByDesc(UserActivity::getCreateTime)
                .last("limit 5")
                .list();
        // 关键的ID
        List<Long> keyIdList = activityList.stream().map(UserActivity::getKeyId).toList();
        if (CollUtil.isEmpty(keyIdList)) {
            return new HashMap<>();
        }
        // code 如果不是订单相关 就去查询商品
        if (ObjectUtil.equal(code, OperationTypeEnum.ORDER_PAY.getCode())) {
            // 如果是订单支付，则去查询订单的所有商品ID ,
            keyIdList = userOrderClient.productIdListByOrderIdList(keyIdList);
        }
        // 查询所有商品的品牌和分类ID，去重。
        return productClient.brandAndCategoryIdsMapByProductIds(keyIdList);
    }
}
